package com.zenithmind.article.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.zenithmind.article.feign.UserFeignClient;
import com.zenithmind.article.mapper.ArticleMapper;
import com.zenithmind.article.mapper.ArticleTagMapper;
import com.zenithmind.article.mapper.CategoryMapper;
import com.zenithmind.article.mapper.TagMapper;
import com.zenithmind.article.pojo.domain.*;
import com.zenithmind.article.pojo.dto.ArticleTagDTO;
import com.zenithmind.article.pojo.vo.ArticleVO;
import com.zenithmind.article.pojo.vo.UserVO;
import com.zenithmind.article.service.ArticleTagAssociationService;
import com.zenithmind.common.result.Result;
import com.zenithmind.common.exception.BusinessException;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import com.zenithmind.common.annotation.DataCacheEvict;

import java.util.*;
import java.util.stream.Collectors;

/**
 * 文章标签关联服务实现
 * 遵循单一职责原则：专注于文章标签关联管理
 * 遵循依赖倒置原则：通过构造器注入依赖
 */
@Slf4j
@Service
public class ArticleTagAssociationServiceImpl implements ArticleTagAssociationService {

    private final ArticleMapper articleMapper;
    private final ArticleTagMapper articleTagMapper;
    private final CategoryMapper categoryMapper;
    private final TagMapper tagMapper;
    private final UserFeignClient userFeignClient;

    // 缓存前缀常量
    private static final String CACHE_ARTICLE_PREFIX = "article";

    // 构造器注入，遵循依赖倒置原则
    public ArticleTagAssociationServiceImpl(
            ArticleMapper articleMapper,
            ArticleTagMapper articleTagMapper,
            CategoryMapper categoryMapper,
            TagMapper tagMapper,
            UserFeignClient userFeignClient) {
        this.articleMapper = articleMapper;
        this.articleTagMapper = articleTagMapper;
        this.categoryMapper = categoryMapper;
        this.tagMapper = tagMapper;
        this.userFeignClient = userFeignClient;
    }

    @Override
    @Transactional
    @DataCacheEvict(prefix = CACHE_ARTICLE_PREFIX, key = "#articleTagDTO.articleId")
    public ArticleVO bindTags(ArticleTagDTO articleTagDTO) {
        log.info("为文章绑定标签: {}", articleTagDTO);
        
        // 验证DTO
        if (!articleTagDTO.isValid()) {
            throw new BusinessException("文章标签关联数据无效");
        }

        // 检查文章是否存在
        Article article = articleMapper.selectById(articleTagDTO.getArticleId());
        if (article == null) {
            throw new BusinessException("文章不存在: " + articleTagDTO.getArticleId());
        }

        // 检查标签是否存在
        validateTagsExist(articleTagDTO.getTagId());

        // 根据操作类型处理标签关联
        if (articleTagDTO.isReplaceOperation()) {
            replaceArticleTags(articleTagDTO.getArticleId(), articleTagDTO.getTagId());
        } else if (articleTagDTO.isRemoveOperation()) {
            removeArticleTags(articleTagDTO.getArticleId(), articleTagDTO.getTagId());
        } else {
            addArticleTags(articleTagDTO.getArticleId(), articleTagDTO.getTagId());
        }

        // 返回更新后的文章信息
        return getArticleWithTags(articleTagDTO.getArticleId());
    }

    @Override
    @Transactional
    @DataCacheEvict(prefix = CACHE_ARTICLE_PREFIX, key = "#articleId")
    public ArticleVO addCategory(String articleId, String categoryId) {
        log.info("为文章添加分类: 文章ID={}, 分类ID={}", articleId, categoryId);
        
        if (StringUtils.isBlank(articleId)) {
            throw new BusinessException("文章ID不能为空");
        }
        if (StringUtils.isBlank(categoryId)) {
            throw new BusinessException("分类ID不能为空");
        }

        // 检查文章是否存在
        Article article = articleMapper.selectById(articleId);
        if (article == null) {
            throw new BusinessException("文章不存在: " + articleId);
        }

        // 检查分类是否存在
        Category category = categoryMapper.selectById(categoryId);
        if (category == null) {
            throw new BusinessException("分类不存在: " + categoryId);
        }

        // 检查分类是否可以添加文章
        if (!category.canAddArticle()) {
            throw new BusinessException("该分类不允许添加文章");
        }

        // 更新文章分类 - 使用 LambdaUpdateWrapper
        articleMapper.update(null,
            new LambdaUpdateWrapper<Article>()
                .eq(Article::getId, articleId)
                .set(Article::getCategoryId, categoryId));

        return getArticleWithTags(articleId);
    }

    @Override
    @Transactional
    public Boolean removeTags(String articleId, List<String> tagIds) {
        log.info("移除文章标签: 文章ID={}, 标签IDs={}", articleId, tagIds);
        
        if (StringUtils.isBlank(articleId) || tagIds == null || tagIds.isEmpty()) {
            return false;
        }

        // 删除指定的标签关联
        int deleted = articleTagMapper.delete(
                new LambdaQueryWrapper<ArticleTag>()
                        .eq(ArticleTag::getArticleId, articleId)
                        .in(ArticleTag::getTagId, tagIds)
        );

        // 更新标签使用次数
        updateTagUsageCount(tagIds, -1);

        return deleted > 0;
    }

    @Override
    @Transactional
    public Boolean updateCategory(String articleId, String categoryId) {
        log.info("更新文章分类: 文章ID={}, 新分类ID={}", articleId, categoryId);
        
        if (StringUtils.isBlank(articleId)) {
            return false;
        }

        Article article = articleMapper.selectById(articleId);
        if (article == null) {
            return false;
        }

        String oldCategoryId = article.getCategoryId();
        
        // 更新文章分类 - 使用 LambdaUpdateWrapper
        int updated = articleMapper.update(null,
            new LambdaUpdateWrapper<Article>()
                .eq(Article::getId, articleId)
                .set(Article::getCategoryId, categoryId));

        // 更新分类文章数量
        if (updated > 0) {
            updateCategoryArticleCount(oldCategoryId, -1);
            updateCategoryArticleCount(categoryId, 1);
        }

        return updated > 0;
    }

    @Override
    public List<String> getArticleTags(String articleId) {
        if (StringUtils.isBlank(articleId)) {
            return Collections.emptyList();
        }

        List<ArticleTag> articleTags = articleTagMapper.selectList(
                new LambdaQueryWrapper<ArticleTag>()
                        .eq(ArticleTag::getArticleId, articleId)
                        .eq(ArticleTag::getStatusCode, 1)
        );

        return articleTags.stream()
                .map(ArticleTag::getTagId)
                .collect(Collectors.toList());
    }

    @Override
    @Transactional
    public Boolean updateTags(String articleId, List<String> tagIds) {
        log.info("批量更新文章标签: 文章ID={}, 标签IDs={}", articleId, tagIds);
        
        if (StringUtils.isBlank(articleId)) {
            return false;
        }

        // 获取当前标签
        List<String> currentTagIds = getArticleTags(articleId);
        
        // 计算需要添加和删除的标签
        List<String> toAdd = tagIds.stream()
                .filter(tagId -> !currentTagIds.contains(tagId))
                .collect(Collectors.toList());
        
        List<String> toRemove = currentTagIds.stream()
                .filter(tagId -> !tagIds.contains(tagId))
                .collect(Collectors.toList());

        // 添加新标签
        if (!toAdd.isEmpty()) {
            addArticleTags(articleId, toAdd);
        }

        // 移除旧标签
        if (!toRemove.isEmpty()) {
            removeTags(articleId, toRemove);
        }

        return true;
    }

    /**
     * 验证标签是否存在
     */
    private void validateTagsExist(List<String> tagIds) {
        List<Tag> existingTags = tagMapper.selectBatchIds(tagIds);
        if (existingTags.size() != tagIds.size()) {
            Set<String> existingTagIds = existingTags.stream()
                    .map(Tag::getId)
                    .collect(Collectors.toSet());
            
            List<String> missingTagIds = tagIds.stream()
                    .filter(tagId -> !existingTagIds.contains(tagId))
                    .collect(Collectors.toList());
            
            throw new BusinessException("标签不存在: " + String.join(", ", missingTagIds));
        }
    }

    /**
     * 添加文章标签关联
     */
    private void addArticleTags(String articleId, List<String> tagIds) {
        // 检查是否已存在关联
        List<ArticleTag> existingAssociations = articleTagMapper.selectList(
                new LambdaQueryWrapper<ArticleTag>()
                        .eq(ArticleTag::getArticleId, articleId)
                        .in(ArticleTag::getTagId, tagIds)
        );

        Set<String> existingTagIds = existingAssociations.stream()
                .map(ArticleTag::getTagId)
                .collect(Collectors.toSet());

        // 只添加不存在的关联
        List<String> newTagIds = tagIds.stream()
                .filter(tagId -> !existingTagIds.contains(tagId))
                .collect(Collectors.toList());

        for (String tagId : newTagIds) {
            ArticleTag articleTag = new ArticleTag(articleId, tagId);
            articleTagMapper.insert(articleTag);
        }

        // 更新标签使用次数
        if (!newTagIds.isEmpty()) {
            updateTagUsageCount(newTagIds, 1);
        }
    }

    /**
     * 移除文章标签关联
     */
    private void removeArticleTags(String articleId, List<String> tagIds) {
        articleTagMapper.delete(
                new LambdaQueryWrapper<ArticleTag>()
                        .eq(ArticleTag::getArticleId, articleId)
                        .in(ArticleTag::getTagId, tagIds)
        );

        // 更新标签使用次数
        updateTagUsageCount(tagIds, -1);
    }

    /**
     * 替换文章标签关联
     */
    private void replaceArticleTags(String articleId, List<String> newTagIds) {
        // 获取当前标签
        List<String> currentTagIds = getArticleTags(articleId);
        
        // 删除所有现有关联
        if (!currentTagIds.isEmpty()) {
            removeArticleTags(articleId, currentTagIds);
        }
        
        // 添加新关联
        if (!newTagIds.isEmpty()) {
            addArticleTags(articleId, newTagIds);
        }
    }

    /**
     * 更新标签使用次数
     */
    private void updateTagUsageCount(List<String> tagIds, int delta) {
        for (String tagId : tagIds) {
            Tag tag = tagMapper.selectById(tagId);
            if (tag != null) {
                if (delta > 0) {
                    tag.incrementUseCount();
                } else {
                    tag.decrementUseCount();
                }
                tagMapper.updateById(tag);
            }
        }
    }

    /**
     * 更新分类文章数量
     */
    private void updateCategoryArticleCount(String categoryId, int delta) {
        if (StringUtils.isBlank(categoryId)) {
            return;
        }
        
        Category category = categoryMapper.selectById(categoryId);
        if (category != null) {
            if (delta > 0) {
                category.incrementArticleCount();
            } else {
                category.decrementArticleCount();
            }
            categoryMapper.updateById(category);
        }
    }

    /**
     * 获取带标签的文章信息
     */
    private ArticleVO getArticleWithTags(String articleId) {
        Article article = articleMapper.selectById(articleId);
        if (article == null) {
            throw new BusinessException("文章不存在");
        }

        ArticleVO articleVO = new ArticleVO();
        BeanUtils.copyProperties(article, articleVO);
        
        // 设置状态码
        articleVO.setStatus(article.getStatusCode());
        
        // 获取用户信息
        try {
            Result<UserVO> userResult = userFeignClient.getUserById(article.getUserId());
            if (userResult != null && userResult.isSuccess() && userResult.getData() != null) {
                articleVO.setUserVo(userResult.getData());
            }
        } catch (Exception e) {
            log.warn("获取用户信息失败: {}", article.getUserId(), e);
        }

        // 获取分类信息
        if (StringUtils.isNotBlank(article.getCategoryId())) {
            Category category = categoryMapper.selectById(article.getCategoryId());
            articleVO.setCategory(category);
        }

        // 获取标签信息
        List<Tag> tags = getArticleTagEntities(articleId);
        articleVO.setTag(tags);

        return articleVO;
    }

    /**
     * 获取文章标签实体
     */
    private List<Tag> getArticleTagEntities(String articleId) {
        List<ArticleTag> articleTags = articleTagMapper.selectList(
                new LambdaQueryWrapper<ArticleTag>()
                        .eq(ArticleTag::getArticleId, articleId)
                        .eq(ArticleTag::getStatusCode, 1)
        );

        if (articleTags.isEmpty()) {
            return Collections.emptyList();
        }

        List<String> tagIds = articleTags.stream()
                .map(ArticleTag::getTagId)
                .collect(Collectors.toList());

        return tagMapper.selectBatchIds(tagIds);
    }
}
